package com.rizzo.infrastructure.dark.redis;

import com.rizzo.infrastructure.dark.DarkLaunchException;
import com.rizzo.infrastructure.dark.DarkLauncher;
import com.rizzo.infrastructure.domain.KeyType;
import com.rizzo.infrastructure.redis.key.RedisKey;
import com.rizzo.infrastructure.redis.key.RedisKeyBuilder;
import org.springframework.data.redis.core.BoundHashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.core.context.SecurityContextHolderStrategy;
import org.springframework.util.StringUtils;

import java.util.Set;


public class RedisDarkLauncher implements DarkLauncher {

    public static final String DARK_LAUNCH_ALLOWED_VALUE = "1";
    public static final String DARK_LAUNCH_DISALLOWED_VALUE = "0";

    private String application;
    private RedisTemplate<RedisKey, String> redisTemplate;
    private SecurityContextHolderStrategy securityContextHolderStrategy;

    public RedisDarkLauncher(String application, RedisTemplate<RedisKey, String> redisTemplate, SecurityContextHolderStrategy securityContextHolderStrategy) {
        this.application = application;
        this.redisTemplate = redisTemplate;
        this.securityContextHolderStrategy = securityContextHolderStrategy;
    }

    public void launchDarkly(String darkLaunchName) {
        Object principal = securityContextHolderStrategy.getContext().getAuthentication().getName();
        RedisKey darkLaunchRedisKey = new RedisKeyBuilder().key(application).type(KeyType.DARK).data(darkLaunchName).build();
        final Set<RedisKey> keys = redisTemplate.keys(darkLaunchRedisKey);
        if (keys != null && !keys.isEmpty()) {
            final BoundHashOperations<RedisKey, String, String> hashOperations = redisTemplate.boundHashOps(darkLaunchRedisKey);
            final String userSwitch = hashOperations.get(principal);
            if (StringUtils.hasText(userSwitch) && DARK_LAUNCH_ALLOWED_VALUE.equals(userSwitch)) {
                // user gains access if the switch was set to DARK_LAUNCH_ALLOWED_VALUE
            } else {
                throw new DarkLaunchException(40477, "dark.launch.exception", new Object[]{darkLaunchName});
            }
        } else {
            // user gains access if no DARK rediskey was present for the functionality
        }
    }
}
